/*
 * Copyright (c) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#ifndef _COMM_FUNCTION_H_
#define _COMM_FUNCTION_H_

#include "napi/native_api.h"
#include <string>
#include <string>
#include <map>
#include <cstdint>

class AutoBuffer;

/*Description: get the last error info into info. If no error, info is an empty string.
*/
void getExceptionSummary(napi_env env, std::string& info);

/*Description: print stack trace info to the string str:
  Return value: napi_ok represents success, otherwise represents failure.
 */
int printStackTrace(napi_env env, std::string& str);

/*Description: Call a non-static or static method by an object or a class:
	Notice:
		Call the object's non_static method: class_or_obj is an object.
  	Call the object's static method: class_or_obj is an class.
  	argc: JS method's parameter number except for an parameter which represents an object or a class.
 */
napi_value JS_CallMethodByName(napi_env env, napi_value class_or_obj, const std::string& method_name, int argc, ...);
napi_value JS_CallMethodByName(napi_env env, napi_value class_or_obj, const std::string& method_name, const char* fmt, ...);
napi_value JS_CallMethodByName(napi_env env, napi_value class_or_obj, napi_value method_name, int argc, ...);
napi_value JS_CallMethodByName(napi_env env, napi_value class_or_obj, napi_value method_name, const char* fmt, ...);

napi_value JS_FindMethodByName(napi_env env, napi_value class_or_obj, const std::string& method_name);

/*Description: Call a static method by a class's name and method name:
	Notice:
		Call the object's non_static method: class_or_obj is an object.
  	Call the object's static method: class_or_obj is an class.
  	argc: JS method's parameter number except for an parameter which represents an object or a class.
 */
napi_value JS_CallStaticMethodByName(napi_env env, const std::string& class_name, const std::string& method_name, int argc, ...);
napi_value JS_CallStaticMethodByName(napi_env env, const std::string& class_name, const std::string& method_name, const char* fmt, ...);

/*Description: Get a class or object's field which has the specified name
	Notice:
		If you pass an object, you will get the object's field (i.e non-static field) rather than its class's field.
		If you pass a class, you will get the class's field field (i.e. static field) rather than its object's field.
 */
napi_value JS_GetProperty(napi_env env, napi_value obj_or_class, const std::string& property_name);

int JS_GetProperty(napi_env env, napi_value obj_or_class, const std::string& property_name, int32_t* value);
int JS_GetProperty(napi_env env, napi_value obj_or_class, const std::string& property_name, uint32_t* value);
int JS_GetProperty(napi_env env, napi_value obj_or_class, const std::string& property_name, int64_t* value);
int JS_GetProperty(napi_env env, napi_value obj_or_class, const std::string& property_name, double* value);

int JS_GetProperty(napi_env env, napi_value obj_or_class, const std::string& property_name, int32_t& value);
int JS_GetProperty(napi_env env, napi_value obj_or_class, const std::string& property_name, uint32_t& value);
int JS_GetProperty(napi_env env, napi_value obj_or_class, const std::string& property_name, int64_t& value);
int JS_GetProperty(napi_env env, napi_value obj_or_class, const std::string& property_name, double& value);

int JS_GetProperty(napi_env env, napi_value obj_or_class, const std::string& property_name, std::string& value);
int JS_GetProperty(napi_env env, napi_value obj_or_class, const std::string& property_name, std::string* value);
int JS_GetProperty(napi_env env, napi_value obj_or_class, const std::string& property_name, bool* value);
int JS_GetProperty(napi_env env, napi_value obj_or_class, const std::string& property_name, bool& value);

int JS_GetAllProperties(napi_env env, napi_value class_or_obj, std::map<std::string, napi_value>& property_map);
int JS_SetAField(napi_env env, napi_value object, const char* field_name, int32_t field_value);
int JS_SetAField(napi_env env, napi_value object, const char* field_name, uint32_t field_value);
int JS_SetAField(napi_env env, napi_value object, const char* field_name, int64_t field_value);
int JS_SetAField(napi_env env, napi_value object, const char* field_name, uint64_t field_value);
int JS_SetAField(napi_env env, napi_value object, const char* field_name, double field_value);
int JS_SetAField(napi_env env, napi_value object, const char* field_name, const char* field_value);
int JS_SetAField(napi_env env, napi_value object, const char* field_name, const std::string& field_value);



/*Description: Get a class's field which has the specified name
	Notice:
		If you pass an object, you will get the object's field (i.e non-static field) rather than its class's field.
		If you pass a class, you will get the class's field field (i.e. static field) rather than its object's field.
 */
napi_value JS_GetStaticField(napi_env env, const std::string& class_name, const std::string& field_name);

int JS_Object2Map(napi_env env, napi_value obj, std::map<std::string, std::string>& strMap);


napi_value JS_Buffer2JbyteArray(napi_env env, const AutoBuffer& ab);
napi_value JS_Buffer2JbyteArray(napi_env env, const void* buffer, size_t length);

bool JS_JbyteArray2Buffer(napi_env env, napi_value arraybuffer, AutoBuffer& ab);

/*
We design these APIs using utf8 string to represent any international characters, rather than using unicode-16 or unicode-32.
*/

// bool JNU_Jstring2Wstring( JNIEnv* _env, const jstring jstr, std::wstring& wstr); //in linux sizeof(wchar_t)==4 but sizeof(jchar)==2

/*
wchar_t* JNU_Jstring2Wchar(JNIEnv* _env, const jstring jstr);
void JNU_FreeWchar(JNIEnv* _env, jstring str, wchar_t* wchar);
jstring JNU_Wstring2Jstring(JNIEnv* _env, const std::wstring& wstr);
jstring JNU_Wchar2JString(JNIEnv* _env, wchar_t* wchar);


// char* to jstring
jstring JNU_Chars2Jstring(JNIEnv* _env, const char* pat);
void JNU_FreeJstring(JNIEnv* _env, jstring str);
*/

/*
std::map<std::string, std::string> JNU_JObject2Map(JNIEnv* _env, const jobject _obj);
*/


typedef void (*js_call_function)(void* data);
typedef struct {
  js_call_function jsfn;
} ExecData;

void RunJs(napi_env env, napi_value js_callback, void* context, void* data);

void WaitForRunJS(void* data);


#endif
